package com.fruitshop.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fruitshop.dto.CartDTO;
import com.fruitshop.entity.Cart;
import com.fruitshop.entity.Fruit;
import com.fruitshop.exception.BusinessException;
import com.fruitshop.mapper.CartMapper;
import com.fruitshop.service.CartService;
import com.fruitshop.service.FruitService;
import com.fruitshop.vo.CartVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 购物车服务实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CartServiceImpl extends ServiceImpl<CartMapper, Cart> implements CartService {
    
    private final FruitService fruitService;
    
    /**
     * 添加购物车
     *
     * @param userId  用户ID
     * @param cartDTO 购物车数据
     * @return 是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean add(Long userId, CartDTO cartDTO) {
        // 检查水果是否存在
        Fruit fruit = fruitService.getById(cartDTO.getFruitId());
        if (fruit == null) {
            throw new BusinessException("水果不存在");
        }
        
        // 检查水果是否上架
        if (fruit.getIsOnSale() != 1) {
            throw new BusinessException("水果已下架");
        }
        
        // 检查库存是否足够
        if (fruit.getStock() < cartDTO.getQuantity()) {
            throw new BusinessException("库存不足");
        }
        
        // 查询是否已存在该水果的购物车项
        Cart cart = getOne(new LambdaQueryWrapper<Cart>()
                .eq(Cart::getUserId, userId)
                .eq(Cart::getFruitId, cartDTO.getFruitId()));
        
        if (cart != null) {
            // 已存在，更新数量
            cart.setQuantity(cart.getQuantity() + cartDTO.getQuantity());
            cart.setSelected(cartDTO.getSelected());
            cart.setUpdateTime(LocalDateTime.now());
            updateById(cart);
        } else {
            // 不存在，新增购物车项
            cart = new Cart();
            cart.setUserId(userId);
            cart.setFruitId(cartDTO.getFruitId());
            cart.setQuantity(cartDTO.getQuantity());
            cart.setSelected(cartDTO.getSelected());
            cart.setCreateTime(LocalDateTime.now());
            cart.setUpdateTime(LocalDateTime.now());
            save(cart);
        }
        
        return true;
    }
    
    /**
     * 修改购物车
     *
     * @param userId  用户ID
     * @param id      购物车ID
     * @param cartDTO 购物车数据
     * @return 是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean update(Long userId, Long id, CartDTO cartDTO) {
        // 查询购物车项是否存在
        Cart cart = getOne(new LambdaQueryWrapper<Cart>()
                .eq(Cart::getId, id)
                .eq(Cart::getUserId, userId));
        
        if (cart == null) {
            throw new BusinessException("购物车项不存在");
        }
        
        // 检查水果是否存在
        Fruit fruit = fruitService.getById(cartDTO.getFruitId());
        if (fruit == null) {
            throw new BusinessException("水果不存在");
        }
        
        // 检查水果是否上架
        if (fruit.getIsOnSale() != 1) {
            throw new BusinessException("水果已下架");
        }
        
        // 检查库存是否足够
        if (fruit.getStock() < cartDTO.getQuantity()) {
            throw new BusinessException("库存不足");
        }
        
        // 更新购物车项
        cart.setQuantity(cartDTO.getQuantity());
        cart.setSelected(cartDTO.getSelected());
        cart.setUpdateTime(LocalDateTime.now());
        updateById(cart);
        
        return true;
    }
    
    /**
     * 删除购物车
     *
     * @param userId 用户ID
     * @param id     购物车ID
     * @return 是否成功
     */
    @Override
    public Boolean delete(Long userId, Long id) {
        return remove(new LambdaQueryWrapper<Cart>()
                .eq(Cart::getId, id)
                .eq(Cart::getUserId, userId));
    }
    
    /**
     * 清空购物车
     *
     * @param userId 用户ID
     * @return 是否成功
     */
    @Override
    public Boolean clear(Long userId) {
        return remove(new LambdaQueryWrapper<Cart>().eq(Cart::getUserId, userId));
    }
    
    /**
     * 获取购物车列表
     *
     * @param userId 用户ID
     * @return 购物车列表
     */
    @Override
    public List<CartVO> list(Long userId) {
        return baseMapper.selectCartList(userId);
    }
    
    /**
     * 更新购物车选中状态
     *
     * @param userId   用户ID
     * @param id       购物车ID
     * @param selected 选中状态
     * @return 是否成功
     */
    @Override
    public Boolean updateSelected(Long userId, Long id, Integer selected) {
        return update(new LambdaUpdateWrapper<Cart>()
                .eq(Cart::getId, id)
                .eq(Cart::getUserId, userId)
                .set(Cart::getSelected, selected)
                .set(Cart::getUpdateTime, LocalDateTime.now()));
    }
    
    /**
     * 全选/取消全选
     *
     * @param userId   用户ID
     * @param selected 选中状态
     * @return 是否成功
     */
    @Override
    public Boolean selectAll(Long userId, Integer selected) {
        return update(new LambdaUpdateWrapper<Cart>()
                .eq(Cart::getUserId, userId)
                .set(Cart::getSelected, selected)
                .set(Cart::getUpdateTime, LocalDateTime.now()));
    }
    
    /**
     * 获取购物车商品数量
     *
     * @param userId 用户ID
     * @return 商品数量
     */
    @Override
    public Integer count(Long userId) {
        // 修复：将 long 转换为 Integer
        return Math.toIntExact(count(new LambdaQueryWrapper<Cart>().eq(Cart::getUserId, userId)));
    }
    
    /**
     * 获取购物车总金额
     *
     * @param userId 用户ID
     * @return 总金额
     */
    @Override
    public BigDecimal getTotalAmount(Long userId) {
        // 查询用户选中的购物车列表
        List<CartVO> cartList = baseMapper.selectSelectedCartList(userId);
        
        // 计算总金额
        BigDecimal totalAmount = BigDecimal.ZERO;
        for (CartVO cart : cartList) {
            totalAmount = totalAmount.add(cart.getSubtotal());
        }
        
        return totalAmount;
    }
} 